#ifndef __SCHEDULER_H_
#define __SCHEDULER_H_

#include <memory>
#include <atomic>
#include <functional>
#include <vector>
#include <list>

#include "thread.h"
#include "fiber.h"


/************************************************
 * Scheduler N(Fiber):M(thread)模型
 * 维护一个全局fiber队列，以及线程池
 * 每个线程会从fiber队列取出任务
 * 默认会将创建Scheduler的调用线程纳入线程池，即会引起调用线程阻塞
 * 
 * 
 * 
 * m_threads:  线程池
 * m_fibers:   fiber队列
 * 
 * scheduler(): 插入Fiber或者插入函数，放入任务队列
 * 
 * m_rootFiber: 线程中的调度fiber
 * m_threadIds: 线程池线程ID,后期fiber可以指定线程运行
 * m_rootThreadID: 调用线程ID，多个线程执行run方法的时候，非rootThread的线程需要主动先创建暂存fiber(调用Fiber::Getthis())
 * 
 * m_activeThreadCount: 线程池中活动线程个数
 * 
 * v_idle :     线程空闲的时候进入该函数，通常该函数由派生类重写，陷入epoll_wait，等待唤醒
 * ticked() :   将线程从idle函数中唤醒
*************************************************/

namespace learnco {

class Scheduler : public std::enable_shared_from_this<Scheduler> {
public:
    typedef std::shared_ptr<Scheduler> ptr;
    typedef learnco::Mutex MutexType;

    Scheduler(size_t threads = 1, const std::string& name = "pool", bool debug = false);
    virtual ~Scheduler();

private:
    std::vector<learnco::Thread::ptr> m_threads;   //线程池
    std::list<learnco::Fiber::ptr> m_fibers;       //fiber全局队列
    learnco::Fiber::ptr m_rootFiber;               //Scheduler的主协程(执行run方法调度fiber)

private:
    MutexType m_mutex;
    std::string m_name;
    bool m_debug;

    
//protected 访问控制，子类可以访问
protected:
    std::vector<int> m_threadIds;
    uint m_threadCount = 0;
    std::atomic<size_t> m_activeThreadCount = {0};
    std::atomic<size_t> m_idleThreadCount = {0};
    int m_rootThreadID = 0;

public:
    void start();
    void stop();

protected:
    void run();
    virtual void v_idle();
    virtual void v_ticked(){};

public:
    void scheduler(learnco::Fiber::ptr f);
    void scheduler(std::function<void()> cb);
    static Scheduler* GetThis();

};

}

#endif